const fs = require('fs');
const path = require('path');
const sharp = require('sharp');
const { promisify } = require('util');

// 使用Node.js内置的fs.promises
const fsPromises = fs.promises;

// 转换为Promise API
const readdir = promisify(fs.readdir);
const stat = promisify(fs.stat);

// 支持的图片格式
const SUPPORTED_FORMATS = ['.png', '.jpg', '.jpeg', '.webp', '.gif', '.tiff'];

/**
 * 检查文件是否为支持的图片类型
 * @param {string} filePath - 文件路径
 * @returns {boolean} 是否为支持的图片
 */
function isSupportedImage(filePath) {
  const ext = path.extname(filePath).toLowerCase();
  return SUPPORTED_FORMATS.includes(ext);
}

/**
 * 根据图片格式设置最佳压缩参数并进行压缩
 * 压缩后若文件变大或节省0%，则不保留输出文件
 * @param {string} inputPath - 输入图片路径
 * @param {string} outputPath - 输出图片路径
 */
async function compressImage(inputPath, outputPath) {
  try {
    const ext = path.extname(inputPath).toLowerCase();
    const image = sharp(inputPath);

    // 对于不同格式使用最佳压缩参数
    const uniQuality = 60
    switch (ext) {
      case '.png':
        await image.png({
          quality: uniQuality,
          compressionLevel: 6,
          force: false
        }).toFile(outputPath);
        break;

      case '.jpg':
      case '.jpeg':
        await image.jpeg({
          quality: uniQuality,
          mozjpeg: true,
          force: false
        }).toFile(outputPath);
        break;

      case '.webp':
        await image.webp({
          quality: uniQuality,
          force: false
        }).toFile(outputPath);
        break;

      case '.gif':
        await image.gif({
          quality: uniQuality,
          force: false
        }).toFile(outputPath);
        break;

      case '.tiff':
        await image.tiff({
          quality: uniQuality,
          force: false
        }).toFile(outputPath);
        break;

      default:
        throw new Error(`不支持的图片格式: ${ext}`);
    }

    // 计算压缩前后的文件大小
    const originalSize = (await stat(inputPath)).size;
    const compressedSize = (await stat(outputPath)).size;
    const savings = ((originalSize - compressedSize) / originalSize * 100).toFixed(2);

    // 关键修改：节省率≤0%时，删除输出文件（不保留）
    if (parseFloat(savings) <= 0) {
      await fsPromises.unlink(outputPath);
      if (parseFloat(savings) < 0) {
        console.log(`压缩后文件变大，已删除: ${path.basename(inputPath)} (变大 ${Math.abs(savings)}%)`);
      } else {
        console.log(`压缩无节省空间，已删除: ${path.basename(inputPath)} (节省 0%)`);
      }
    } else {
      console.log(`压缩成功: ${path.basename(inputPath)} (节省 ${savings}%)`);
    }
  } catch (error) {
    console.error(`压缩失败: ${inputPath} - ${error.message}`);
  }
}

/**
 * 递归遍历目录并处理所有图片
 * @param {string} inputDir - 输入目录
 * @param {string} outputDir - 输出目录
 */
async function processDirectory(inputDir, outputDir) {
  try {
    await fsPromises.mkdir(outputDir, { recursive: true });

    const entries = await readdir(inputDir, { withFileTypes: true });

    for (const entry of entries) {
      const inputPath = path.join(inputDir, entry.name);
      const outputPath = path.join(outputDir, entry.name);

      if (entry.isDirectory()) {
        await processDirectory(inputPath, outputPath);
      } else if (entry.isFile() && isSupportedImage(inputPath)) {
        await compressImage(inputPath, outputPath);
      }
    }
  } catch (error) {
    console.error(`处理目录出错: ${inputDir} - ${error.message}`);
  }
}

/**
 * 主函数
 * @param {string} inputDir - 输入目录路径
 * @param {string} outputDir - 输出目录路径
 */
async function main(inputDir, outputDir) {
  if (!inputDir || !outputDir) {
    console.error('请提供输入目录和输出目录');
    console.log('用法: node image-compressor.js <输入目录> <输出目录>');
    process.exit(1);
  }

  const resolvedInput = path.resolve(inputDir);
  const resolvedOutput = path.resolve(outputDir);

  try {
    await stat(resolvedInput);
  } catch (error) {
    console.error(`输入目录不存在: ${resolvedInput}`);
    process.exit(1);
  }

  console.log(`开始图片压缩...`);
  console.log(`输入目录: ${resolvedInput}`);
  console.log(`输出目录: ${resolvedOutput}`);
  console.log('------------------------------');

  try {
    await processDirectory(resolvedInput, resolvedOutput);
    console.log('------------------------------');
    console.log('所有图片处理完成!');
  } catch (error) {
    console.error('处理过程中发生错误:', error.message);
    process.exit(1);
  }
}

// 从命令行获取参数
const [, , inputDir, outputDir] = process.argv;
main(inputDir, outputDir);